import React, { ReactNode } from 'react';
import { Tree } from 'antd';
import { AntTreeNodeCheckedEvent, AntTreeNodeSelectedEvent } from 'antd/lib/tree';

import { agentShareList } from '@/services/assistantCenter';
import { getAssistantShareList } from '@/services/digitalEmployees';

import styles from './index.module.less';

const { TreeNode }: any = Tree;

export const AgentTypeNameEnum = {
  '智能体': '智能体',
  '通用能力': '通用能力',
  'all': 'all',
};

const enum ABILITY_TYPE_ENUM {
  '通用助手' = 2,
  '智能体' = 3,
};

interface ITreeType {
  dataList: any[];
  checkedKeys: string[];
  expandedKeys: string[];
  agentIds: string[];
}

interface IProp {
  onRef?: (el: ReactNode) => ReactNode;
  applicationId: string;
  agentTypeName?: '智能体' | '通用能力' | 'all';
  defaultCheckedKeys?: string[];
  multiple?: boolean;
  handleSelectedAbilitiesChange: (ids: string[], nodes: any[], abilityType?: ABILITY_TYPE_ENUM) => void;
}

interface IState {
  generalAgentTree: ITreeType;
  digitalStaffTree: ITreeType;
}

class GeneralAbilityTree extends React.Component<IProp, IState> {
  constructor(props: IProp) {
    super(props);
    this.state = {
      generalAgentTree: {
        dataList: [],
        checkedKeys: [],
        expandedKeys: [],
        agentIds: [],
      },
      digitalStaffTree: {
        dataList: [],
        checkedKeys: [],
        expandedKeys: [],
        agentIds: [],
      },
    };
  }

  componentDidMount(): void {
    this.props.onRef?.(this);
    this.fetchData();
  }

  fetchData = async () => {
    this.getGeneralAgentData();
    this.getDigitalStaffData();
  }

  getGeneralAgentData = async () => {
    const { applicationId, defaultCheckedKeys = [] } = this.props;
    const dataList = await agentShareList({ applicationId });
    const categoryIds = [];
    const agentIds = [];

    const traverse = (dataList) => {
      for (let i = 0, len = dataList.length; i < len; i++) {
        const data = dataList[i];
        if (data.id === applicationId) {
          this.removeMyself(dataList, i);
          continue;
        }
        if (data.children?.length > 0) {
          traverse(data.children);
        }
        if (data.isCategory) {
          categoryIds.push(data.id);
        } else {
          agentIds.push(data.id);
        }
      }
    }

    traverse([dataList]);

    this.setState(({ generalAgentTree }) => ({
      generalAgentTree: {
        ...generalAgentTree,
        dataList: [dataList],
        checkedKeys: defaultCheckedKeys,
        expandedKeys: categoryIds,
        agentIds,
      },
    }));
  }

  getDigitalStaffData = async () => {
    const { applicationId, defaultCheckedKeys = [] } = this.props;
    const dataList = await getAssistantShareList({ applicationId });
    const categoryIds = [];
    const agentIds = [];

    const traverse = (dataList) => {
      for (let i = 0, len = dataList.length; i < len; i++) {
        const data = dataList[i];
        if (data.id === applicationId) {
          this.removeMyself(dataList, i);
          continue;
        }
        if (data.children?.length > 0) {
          traverse(data.children);
        }
        if (!data.tenantId) {
          categoryIds.push(data.id);
        } else {
          agentIds.push(data.id);
        }
      }
    }

    traverse([dataList]);

    this.setState(({ digitalStaffTree }) => ({
      digitalStaffTree: {
        ...digitalStaffTree,
        dataList: [dataList],
        checkedKeys: defaultCheckedKeys,
        expandedKeys: categoryIds,
        agentIds,
      },
    }));
  }

  /**
   * 如果当前组件的调用者本身也是助手或数字员工，则隐藏他自己
   * @param list 
   * @param index 
   */
  removeMyself = (list: any[], index: number) => {
    list.splice(index, 1);
  }

  renderNestedTree = (dataList) => {
    return dataList.map(data => {
      if (data.children) {
        return (
          <TreeNode key={data.id} title={data.name} dataRef={data}>
            {this.renderNestedTree(data.children)}
          </TreeNode>
        );
      }

      return <TreeNode key={data.id} title={data.name} {...data} />;
    });
  }

  handleGeneralAgentTreeCheck = (checkedKeys: string[], { checkedNodes }: AntTreeNodeCheckedEvent) => {
    const { generalAgentTree: { agentIds } } = this.state;
    const checkedAgentKeys = checkedKeys.filter(key => agentIds.includes(key));
    const checkedAgentNodes = checkedNodes.map(node => node.props).filter(node => agentIds.includes(node.id));
    this.setState(({ generalAgentTree }) => ({
      generalAgentTree: { ...generalAgentTree, checkedKeys },
    }));
    this.props.handleSelectedAbilitiesChange(checkedAgentKeys, checkedAgentNodes);
  }

  handleGeneralAgentTreeExpand = (expandedKeys: string[]) => {
    this.setState(({ generalAgentTree }) => ({
      generalAgentTree: { ...generalAgentTree, expandedKeys },
    }));
  }

  handleGeneralAgentTreeSelect = (selectedKeys: string[], { selectedNodes }: AntTreeNodeSelectedEvent) => {
    const { generalAgentTree: { agentIds } } = this.state;
    const checkedAgentKeys = selectedKeys.filter(key => agentIds.includes(key));
    const checkedAgentNodes = selectedNodes.map(node => node.props).filter(node => agentIds.includes(node.id));
    this.setState(({ digitalStaffTree, generalAgentTree }) => ({
      digitalStaffTree: { ...digitalStaffTree, checkedKeys: [] },
      generalAgentTree: { ...generalAgentTree, checkedKeys: checkedAgentKeys },
    }));
    this.props.handleSelectedAbilitiesChange(checkedAgentKeys, checkedAgentNodes, ABILITY_TYPE_ENUM.通用助手);
  }

  handleDigitalStaffTreeCheck = (checkedKeys: string[], { checkedNodes }: AntTreeNodeCheckedEvent) => {
    const { digitalStaffTree: { agentIds } } = this.state;
    const checkedAgentKeys = checkedKeys.filter(key => agentIds.includes(key));
    const checkedAgentNodes = checkedNodes.map(node => node.props).filter(node => agentIds.includes(node.id));
    this.setState(({ digitalStaffTree }) => ({
      digitalStaffTree: { ...digitalStaffTree, checkedKeys },
    }));
    this.props.handleSelectedAbilitiesChange(checkedAgentKeys, checkedAgentNodes);
  }

  handleDigitalStaffTreeExpand = (expandedKeys: string[]) => {
    this.setState(({ digitalStaffTree }) => ({
      digitalStaffTree: { ...digitalStaffTree, expandedKeys },
    }));
  }

  handleDigitalStaffTreeSelect = (selectedKeys: string[], { selectedNodes }: AntTreeNodeSelectedEvent) => {
    const { digitalStaffTree: { agentIds } } = this.state;
    const checkedAgentKeys = selectedKeys.filter(key => agentIds.includes(key));
    const checkedAgentNodes = selectedNodes.map(node => node.props).filter(node => agentIds.includes(node.id));
    this.setState(({ digitalStaffTree, generalAgentTree }) => ({
      digitalStaffTree: { ...digitalStaffTree, checkedKeys: checkedAgentKeys },
      generalAgentTree: { ...generalAgentTree, checkedKeys: [] },
    }));
    this.props.handleSelectedAbilitiesChange(checkedAgentKeys, checkedAgentNodes, ABILITY_TYPE_ENUM.智能体);
  }

  render() {
    const { agentTypeName = AgentTypeNameEnum.all, multiple = true } = this.props;
    const { generalAgentTree, digitalStaffTree } = this.state;

    return (
      <div className={`${styles['general-ability-tree']}`}>
        {agentTypeName !== AgentTypeNameEnum.智能体 && (
          <div className={`${styles['general-agent-tree']}`}>
            <Tree
              autoExpandParent={true}
              checkable={multiple}
              checkedKeys={generalAgentTree.checkedKeys}
              expandedKeys={generalAgentTree.expandedKeys}
              multiple={multiple}
              selectable={!multiple}
              selectedKeys={generalAgentTree.checkedKeys}
              onCheck={this.handleGeneralAgentTreeCheck}
              onExpand={this.handleGeneralAgentTreeExpand}
              onSelect={this.handleGeneralAgentTreeSelect}
            >
              {this.renderNestedTree(generalAgentTree.dataList)}
            </Tree>
          </div>
        )}
        {agentTypeName !== AgentTypeNameEnum.通用能力 && (
          <div className={`${styles['digital-staff-tree']}`}>
            <Tree
              autoExpandParent={true}
              checkable={multiple}
              checkedKeys={digitalStaffTree.checkedKeys}
              expandedKeys={digitalStaffTree.expandedKeys}
              multiple={multiple}
              selectable={!multiple}
              selectedKeys={digitalStaffTree.checkedKeys}
              onCheck={this.handleDigitalStaffTreeCheck}
              onExpand={this.handleDigitalStaffTreeExpand}
              onSelect={this.handleDigitalStaffTreeSelect}
            >
              {this.renderNestedTree(digitalStaffTree.dataList)}
            </Tree>
          </div>
        )}
      </div>
    );
  }
}

export default GeneralAbilityTree;
